package com.threeti.mecool.core.infrastructure.persistence.plan;

import com.threeti.mecool.core.domain.model.plan.UserStepResult;
import org.joda.time.DateTime;
import org.springframework.data.jpa.domain.Specification;

import javax.persistence.criteria.*;
import java.util.Date;
import java.util.List;

public abstract class UserStepResultSpecs {

    public static Specification<UserStepResult> actionIdIs(final Integer actionId) {
        return new Specification<UserStepResult>() {
            @Override
            public Predicate toPredicate(Root<UserStepResult> usrRoot, CriteriaQuery<?> query, CriteriaBuilder cb) {
                return cb.equal(usrRoot.<Integer>get("actionId"), actionId);
            }
        };
    }

    public static Specification<UserStepResult> dataTypeIdIn(final List<Long> taskActionDataTypeIds) {
        return new Specification<UserStepResult>() {
            @Override
            public Predicate toPredicate(Root<UserStepResult> usrRoot, CriteriaQuery<?> query, CriteriaBuilder cb) {
                return usrRoot.<Long>get("dataTypeId").in(taskActionDataTypeIds);
            }
        };
    }

    public static Specification<UserStepResult> finishedAtWithin(final Date finishedAt) {
        return new Specification<UserStepResult>() {
            @Override
            public Predicate toPredicate(Root<UserStepResult> usrRoot, CriteriaQuery<?> query, CriteriaBuilder cb) {
                DateTime time = new DateTime(finishedAt.getTime());
                DateTime startOfTheDay = time.withTimeAtStartOfDay();
                DateTime endOfTheDay = startOfTheDay.plusDays(1).minusMillis(1);
                return cb.between(usrRoot.<Date>get("finishedAt"), startOfTheDay.toDate(), endOfTheDay.toDate());
            }
        };
    }

    public static Specification<UserStepResult> finishedAtGe(final Date finishedAt) {
        return new Specification<UserStepResult>() {
            @Override
            public Predicate toPredicate(Root<UserStepResult> usrRoot, CriteriaQuery<?> query, CriteriaBuilder cb) {
                DateTime time = new DateTime(finishedAt.getTime());
                DateTime startOfTheDay = time.withTimeAtStartOfDay();
                return cb.greaterThanOrEqualTo(usrRoot.<Date>get("finishedAt"), startOfTheDay.toDate());
            }
        };
    }

    public static Specification<UserStepResult> finishedAtLe(final Date finishedAt) {
        return new Specification<UserStepResult>() {
            @Override
            public Predicate toPredicate(Root<UserStepResult> usrRoot, CriteriaQuery<?> query, CriteriaBuilder cb) {
                DateTime time = new DateTime(finishedAt.getTime()).plusDays(1);
                DateTime startOfTheDay = time.withTimeAtStartOfDay();
                return cb.lessThan(usrRoot.<Date>get("finishedAt"), startOfTheDay.toDate());
            }
        };
    }

    public static Specification<UserStepResult> empNameLike(final String empName) {
        return new Specification<UserStepResult>() {
            @Override
            public Predicate toPredicate(Root<UserStepResult> usrRoot, CriteriaQuery<?> query, CriteriaBuilder cb) {
                return cb.like(usrRoot.<String>get("empName"), "%" + empName + "%");
            }
        };
    }

    public static Specification<UserStepResult> storeChannelNameLike(final String storeChannelName) {
        return new Specification<UserStepResult>() {
            @Override
            public Predicate toPredicate(Root<UserStepResult> usrRoot, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Path<String> channelNamePath = usrRoot.get("planJobResult").get("channel").get("channel").get("name");
                return cb.like(channelNamePath, "%" + storeChannelName + "%");
            }
        };
    }

    public static Specification<UserStepResult> projectNameLike(final String projectName) {
        return new Specification<UserStepResult>() {
            @Override
            public Predicate toPredicate(Root<UserStepResult> usrRoot, CriteriaQuery<?> query, CriteriaBuilder cb) {
                return cb.like(usrRoot.<String>get("projectName"), "%" + projectName + "%");
            }
        };
    }

    public static Specification<UserStepResult> projectCodeIs(final String projectCode) {
        return new Specification<UserStepResult>() {
            @Override
            public Predicate toPredicate(Root<UserStepResult> usrRoot, CriteriaQuery<?> query, CriteriaBuilder cb) {
                return cb.equal(usrRoot.<String>get("projectCode"), projectCode);
            }
        };
    }

    public static Specification<UserStepResult> projectCodeIn(final List<String> projectCodes) {
        return new Specification<UserStepResult>() {
            @Override
            public Predicate toPredicate(Root<UserStepResult> usrRoot, CriteriaQuery<?> query, CriteriaBuilder cb) {
                return usrRoot.<String>get("projectCode").in(projectCodes);
            }
        };
    }
}
